package com.sghj.utils;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.alibaba.fastjson.JSONObject;
import com.sghj.config.handler.ResultCode;
import com.sghj.config.handler.exceptionHandler.MyException;
import com.sghj.utils.file.FileUtil;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Map;

/**
 * @author xrx
 * 上传图片工具类
 * @Date 2022/3/10
 * @apiNote
 */
@Slf4j
@Component
public class UploadImgUtils {
    @Value("${upload.path}")
    private String uploadPath;

    private static String PREFIX = "data:image/jpg;base64,";

    public static String defaultPhoto = "";
    /**
     * 上传图片
     * @param file
     * @param dir
     * @return
     */
    public static String uploadImg(MultipartFile file,String dir){
        try {
            String realFileName = file.getOriginalFilename();
            //获取文件后缀
            String imgSuffix = realFileName.substring(realFileName.lastIndexOf("."));
            //生成唯一文件名
            String newFileName = UUIDUtils.getUUID32().toString()+imgSuffix;
            //生成时间路径
            SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMDD");
            String datePath = sdf.format(new Date());
            //指定文件上传目录
            //File targetPath = new File("/home/ubuntu/resource/picture/"+dir,datePath);
            File targetPath = new File("C:\\recdata\\picture\\"+dir,datePath);
            //System.out.println(targetPath);
            //如果路径不存在
            if (!targetPath.exists()){
                targetPath.mkdirs();
            }
            File targetFileName = new File(targetPath,newFileName);
            //文件上传到指定目录
            file.transferTo(targetFileName);
            //获取图片地址
            String imgPath = "http://10.94.21.26:8090/picture/"+dir+"/"+datePath+"/"+newFileName;
            return imgPath;
        }catch (Exception e){
            e.printStackTrace();
            throw new MyException(ResultCode.UPLOADFAIL,"上传图片失败");
        }
    }

    /**
     * 删除服务器照片
     * @param imageUrl
     * @return
     */
    public static boolean deleteImg(String imageUrl){
        String filePath="C:\\recdata\\picture\\"+imageUrl;
        //String filePath="D:\\temp\\"+imageUrl;
        //System.out.println(filePath);
        File file = new File(filePath);
        if (file.exists()) {
            boolean flag = file.delete(); // 删除照片
            return flag;
        }else {
            return true;
        }
    }

    /**
     * 照片转base64格式
     * @param photo
     * @return
     */
    public static String getBase64Photo(MultipartFile photo) {
        if (photo.equals("")){
            return "";
        }

        //获取文件名称
        String originalFilename = photo.getOriginalFilename();
        //截取文件后缀
        final String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();

        if (photo.isEmpty()||!FileUtil.IMAGE_EXTENSIONS.contains(suffix)){
            throw new MyException(ResultCode.PARAMETER,"请传入有效图片");
        }

        String base64Photo = "";
        try {
            base64Photo = PREFIX + Base64Encoder.encode(photo.getBytes());      //拼图片前缀
            //base64Photo = Base64Encoder.encode(photo.getBytes());               //不拼图片前缀
        } catch (IOException e) {
            throw new MyException(ResultCode.CREATEBASE64,"转换Base64失败");
        }
        return base64Photo;
    }

    /**
     * 生成base64缩略图
     * @param photo
     * @return
     */
    public static String getThumbnailBase64Photo(MultipartFile photo) throws IOException {

        if (photo==null){
            return null;
        }
        //获取文件名称
        String originalFilename = photo.getOriginalFilename();
        //截取文件后缀
        final String suffix = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();

        if (photo.isEmpty()||!FileUtil.IMAGE_EXTENSIONS.contains(suffix)){
            throw new MyException(ResultCode.PARAMETER,"请传入有效图片");
        }

        if (photo.getSize()>2*1024*1024){
            throw new MyException(ResultCode.FILEUPLOADERROR,"文件大小请勿超过2M");
        }

        byte[] data = photo.getBytes();
        //如果小于30kb，不进行压缩
        if (photo.getSize()<=1024*150){
                return PREFIX + Base64Encoder.encode(data);      //拼图片前缀
        }
        //大小大于20kb，进行压缩
        long srcSize = data.length;
        double accuracy = getAccuracy(srcSize / 1024);

        while (data.length > 1024*150){
            ByteArrayInputStream in = new ByteArrayInputStream(data);
            ByteArrayOutputStream out = new ByteArrayOutputStream(data.length);

            Thumbnails.of(in)
                    .scale(accuracy)
                    //.size(destWidth,destHeight)
                    .outputQuality(accuracy)
                    .toOutputStream(out);

            data = out.toByteArray();

            System.out.println("压缩后数据大小=======" + data.length);
        }
        System.out.println("压缩后数据大小=======" + data.length);
        return PREFIX + Base64.getEncoder().encodeToString(data);
    }


    /**
     * 照片转base64格式
     * @param photo
     * @return
     */
    public static String getBase64Photo(String photo) {
        if (photo.equals("")){
            return "";
        }

        //获取文件名称
        File file = new File(photo);
        InputStream in = null;
        byte[] data =null;
        //读取图片字节数组
        try {
            in = new FileInputStream(file);
            data = new byte[in.available()];
            in.read(data);
            in.close();
            if (data!=null&&data.length>0){
                //删除图片
                file.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        String base64Photo = "";
        base64Photo = PREFIX + Base64Encoder.encode(data);      //拼图片前缀
        return base64Photo;
    }

    /**
     * 根据员工id生成二维码
     * @param employeeId
     * @return
     */
    public static String getQRCodeById(Integer employeeId) throws IOException {
        if (employeeId==null){
            throw new MyException(ResultCode.PARAMETER,"没有获取到用户id");
        }

        File d = new File("");
        String path = d.getCanonicalPath();     //绝对路径
        //String path2 = path+"\\picture\\logo.png";      //编译后的静态文件路径
        String path2 = "C:\\zjcqdata\\picture\\logo.png";      //编译后的静态文件路径
        QrConfig config = new QrConfig();
        config.setImg(path2);      //插入logo

        BufferedImage bufferedImage = QrCodeUtil.generate(Integer.toBinaryString(employeeId),
                config.create().setWidth(270).setHeight(270).setMargin(0).setImg(path2)
                );

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "JPEG", os);
        os.flush();
        os.close();

        String QRCode = "data:image/bmp;base64,"+Base64Encoder.encode(os.toByteArray());

        return QRCode;
    }

    // 对字节数组字符串进行Base64解码并生成图片
    //imgFilePath 待保存的本地路径
    public static boolean GenerateImage(String base64Str, String imgFilePath) {
        if (base64Str == null) // 图像数据为空
            return false;
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            // Base64解码
            byte[] bytes = decoder.decodeBuffer(base64Str);
            for (int i = 0; i < bytes.length; ++i) {
                if (bytes[i] < 0) {// 调整异常数据
                    bytes[i] += 256;
                }
            }
            // 生成jpeg图片
            OutputStream out = new FileOutputStream(imgFilePath);
            out.write(bytes);
            out.flush();
            out.close();
            //====
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 900) {
            accuracy = 0.85;
        } else if (size < 2047) {
            accuracy = 0.6;
        } else if (size < 3275) {
            accuracy = 0.44;
        } else {
            accuracy = 0.4;
        }
        return accuracy;
    }

    /**
     * 请求图片地址, 返回的结果进行base64编码
     * @param imgUrl 图片地址
     * @return
     */
    public static String requestUrlToBase64(String imgUrl) {
        if(StringUtils.isEmpty(imgUrl)){
            return null;
        }

        String result = null;
        HttpURLConnection connection = null;

        try {
            URL url = new URL(imgUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(1000);
            connection.setReadTimeout(1000);
            // 获取请求输入流
            InputStream inputStream = connection.getInputStream();

            // inputStream流数据转ByteArrayOutputStream
            int len = -1;
            byte[] buffer = new byte[1024];
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            while ((len = inputStream.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }

            // ByteArrayOutputStream编码成base64字符串
            result = new String(Base64.getEncoder().encode(out.toByteArray()));
            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(connection != null){
                connection.disconnect();
            }
        }

        return PREFIX+result;
    }

    /**
     * 生成二维码
     * @param
     * @return
     */
    public String getQRCode(Map<String,String> content, String fileName) throws IOException, FontFormatException {
        if (StringUtils.isEmpty(content)) {
            throw new MyException(ResultCode.PARAMETER, "缺少参数");
        }
        //logo地址
        String path2 = "C:\\zjcqdata\\picture\\logo.png";
        QrConfig config = new QrConfig();
        config.setImg(path2);      //插入logo

        String codeImgFileSaveDir = uploadPath + "dinnerQrCode/";     //二维码存储路径
        File file = new File(codeImgFileSaveDir);
        if (!file.exists()) {
            //二维码图片存放目录不存在，开始创建...
            file.mkdirs();
        }
        String equipmentName = content.get("equipmentName");
        //content.remove("equipmentName");
        //二维码内容
        String encrypt = SM4Utils.encrypt(JSONObject.toJSONString(content));
        BufferedImage bufferedImage = QrCodeUtil.generate(encrypt,
                    config.create().setWidth(790).setHeight(790).setMargin(0).setImg(path2)
            );
        int height = bufferedImage.getHeight();
        int width = bufferedImage.getWidth();
        int[] ImageArrayOne = new int[height*width];
        ImageArrayOne = bufferedImage.getRGB(0,0,height,width,ImageArrayOne,0,width);

        //底图
        BufferedImage BasemapImage = ImageIO.read(new File("C:\\zjcqdata\\picture\\qrcode.jpg"));

        //文字
        String groupName = content.get("name");
        String equipment = content.get("equipmentName");

        String name = groupName+equipment;
        //设置背景
        Graphics2D g2 = BasemapImage.createGraphics();
        //设置字体
        int fontSize = getFontSize(name.length(),1440);

        g2.setFont(new Font("黑体",Font.PLAIN,fontSize));
        g2.setColor(Color.BLACK);

        //第一行：餐厅
        g2.drawString(name,getX(name,1772,fontSize),1650);
        //drawString(g2,name,getX(name,1300),1600,1300-g2.getFontMetrics().charWidth(' '));
        //第二行：设备名
        //drawString(g2,equipmentName,getX(equipmentName,1772),1700,1772-g2.getFontMetrics().charWidth(' '));

        //g2.drawString(name,50,300);
        //拼接图片
        BasemapImage.setRGB(485,690,790,790,ImageArrayOne,0,790);

        //输出png图片
        File codeImgFile = new File(file, fileName);
        ImageIO.write(BasemapImage,"png",codeImgFile);
        g2.dispose();
        log.info("生成就餐二维码成功：" + codeImgFile.getPath());

        //File codeImgFile = new File(file, fileName);
        //ImageIO.write(bufferedImage, "png", codeImgFile);
        //
        //log.info("生成就餐二维码成功：" + codeImgFile.getPath());
        return "/picture/dinnerQrCode/"+fileName;
    }

    private int getFontSize(int strLength,int width){
        double fontSize = 93.2;
        double strWidth = strLength*fontSize;
        if (strWidth>width){
            fontSize =width/strLength;
        }
        return (int)fontSize;
    }

    private int getX(String str, int width,int fontSize) {
        int x = width/2-str.length()*fontSize/2;
        if (str.length()*fontSize>=1400){
            x = 186;
        }
        return x;
    }

    /**
     * Graphic2D文本绘制换行，多行绘制
     *
     * @param g  Graphics2D画笔实例
     * @param strContent        需要绘制的文本内容
     * @param startX      X坐标起始点（像素）
     * @param startY      Y坐标起始点（像素）
     * @param rowWidth    一行的总宽度（像素）
     */
    public static int drawString(Graphics g, String strContent, int startX, int startY, int rowWidth){
        //每行间距（像素）
        int heightSpace = 2;
        //获取画笔的字体
        Font font = g.getFont();
        //通过JLabel获取文本的总长度和总高度
        JLabel jLabel = new JLabel(strContent);
        jLabel.setFont(font);
        FontMetrics fontMetrics = jLabel.getFontMetrics(font);
        int textLength = strContent.length();
        //一行的总长度，用于判断是否超出了范围
        int totalWidth = fontMetrics.stringWidth(strContent);
        //计算一行的高度
        int textHeight = fontMetrics.getHeight();
        if (totalWidth > rowWidth) {
            // 总长度超过了整个长度限制
            //已经写了多少行
            int alreadyWriteLine = 0;
            //目前一行写的长度
            int nowWidth = 0;
            for (int i = 0; i < textLength; i++) {
                //获取单个字符的长度
                int oneWordWidth = fontMetrics.charWidth(strContent.charAt(i));
                //判断目前的一行加上这个字符的长度是否超出了总长度
                int tempWidth = oneWordWidth + nowWidth;
                if (tempWidth > rowWidth) {
                    //如果超出了一行的总长度，则要换成下一行
                    nowWidth = 0;
                    alreadyWriteLine++;
                    int writeY = startY + alreadyWriteLine * (textHeight + heightSpace);
                    g.drawString(strContent.charAt(i) + "", startX + nowWidth, writeY);
                    nowWidth = oneWordWidth;
                } else {
                    //当前行长度足够，可以直接画
                    int writeY = startY + alreadyWriteLine * (textHeight + heightSpace);
                    g.drawString(strContent.charAt(i) + "", startX + nowWidth, writeY);
                    nowWidth = tempWidth;
                }
            }
            return alreadyWriteLine;
        } else {
            //没有超过限制，直接画
            g.drawString(strContent, startX, startY);
            return 1;
        }
    }
}
